﻿///////////////////////////////////////////////////////////////////////////////
///
/// ConvertExt.cs
///
/// (c)2017 Kim, Hyoun Woo
///
///////////////////////////////////////////////////////////////////////////////
using UnityEngine;
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace DLC.Module.DataTable
{
    /// <summary>
    /// DataTable specific a helper class for various type converting. 
    /// 
    /// </summary>
    public partial class ConvertExt
    {
        public static string SingleArrayToString(object value, char delimiter = ',')
        {
            try
            {
                float[] vals = (float[])value;
                StringBuilder sb = new StringBuilder();
                foreach (var val in vals)
                {
                    sb.Append(val).Append(delimiter);
                }
                sb.Remove(sb.Length - 1, 1);
                return sb.ToString();
            }catch(Exception e)
            {
                throw e;
            }
        }

        public static string DoubleArrayToString(object value, char delimiter = ',')
        {
            try
            {
                double[] vals = (double[])value;
                StringBuilder sb = new StringBuilder();
                foreach (var val in vals)
                {
                    sb.Append(val).Append(delimiter);
                }
                sb.Remove(sb.Length - 1, 1);
                return sb.ToString();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public static string Int16ArrayToString(object value, char delimiter = ',')
        {
            try
            {
                short[] vals = (short[])value;
                StringBuilder sb = new StringBuilder();
                foreach (var val in vals)
                {
                    sb.Append(val).Append(delimiter);
                }
                sb.Remove(sb.Length - 1, 1);
                return sb.ToString();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public static string Int32ArrayToString(object value, char delimiter = ',')
        {
            try
            {
                int[] vals = (int[])value;
                StringBuilder sb = new StringBuilder();
                foreach (var val in vals)
                {
                    sb.Append(val).Append(delimiter);
                }
                sb.Remove(sb.Length - 1, 1);
                return sb.ToString();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public static string Int64ArrayToString(object value, char delimiter = ',')
        {
            try
            {
                long[] vals = (long[])value;
                StringBuilder sb = new StringBuilder();
                foreach (var val in vals)
                {
                    sb.Append(val).Append(delimiter);
                }
                sb.Remove(sb.Length - 1, 1);
                return sb.ToString();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public static string StringArrayToString(object value, char delimiter = ',')
        {
            try
            {
                string[] vals = (string[])value;
                StringBuilder sb = new StringBuilder();
                foreach (var val in vals)
                {
                    sb.Append(val).Append(delimiter);
                }
                sb.Remove(sb.Length - 1, 1);
                return sb.ToString();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public static string Vector2ToString(object data, char delimiterVector = ',')
        {
            Vector2 value = (Vector2)data;

            return $"{value.x}{delimiterVector}{value.y}";
        }

        public static string Vector2IntToString(object data, char delimiterVector = ',')
        {
            //Vector2Int value = (Vector2Int)Convert.ChangeType(data,typeof(Vector2Int));
            Vector2Int value = (Vector2Int)data;

            return $"{value.x}{delimiterVector}{value.y}";
        }
        public static string Vector3ToString(object data, char delimiterVector = ',')
        {
            //Vector3 value = (Vector3)Convert.ChangeType(data,typeof(Vector3));
            Vector3 value = (Vector3)data;

            return $"{value.x}{delimiterVector}{value.y}{delimiterVector}{value.z}";
        }
        public static string Vector3IntToString(object data, char delimiterVector = ',')
        {
            //Vector3 value = (Vector3)Convert.ChangeType(data,typeof(Vector3));
            Vector3Int value = (Vector3Int)data;

            return $"{value.x}{delimiterVector}{value.y}{delimiterVector}{value.z}";
        }
        public static string Vector4ToString(object data, char delimiterVector = ',')
        {
            //Vector3 value = (Vector3)Convert.ChangeType(data,typeof(Vector3));
            Vector4 value = (Vector4)data;

            return $"{value.x}{delimiterVector}{value.y}{delimiterVector}{value.z}{delimiterVector}{value.w}";
        }
        public static string Vector2ArrayToString(object data, char delimiter = ';', char delimiterVector = ',')
        {
            //Vector3 value = (Vector3)Convert.ChangeType(data,typeof(Vector3));
            Vector2[] value = (Vector2[])data;
            StringBuilder sb = new StringBuilder();
            foreach(var val in value)
            {
                sb.Append(val.x).Append(delimiterVector).Append(val.y).Append(delimiter);
            }
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }
        public static string Vector2IntArrayToString(object data, char delimiter = ';', char delimiterVector = ',')
        {
            //Vector3 value = (Vector3)Convert.ChangeType(data,typeof(Vector3));
            Vector2Int[] value = (Vector2Int[])data;
            StringBuilder sb = new StringBuilder();
            foreach (var val in value)
            {
                sb.Append(val.x).Append(delimiterVector).Append(val.y).Append(delimiter);
            }
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }
        public static string Vector3ArrayToString(object data, char delimiter = ';', char delimiterVector = ',')
        {
            //Vector3 value = (Vector3)Convert.ChangeType(data,typeof(Vector3));
            Vector3[] value = (Vector3[])data;
            StringBuilder sb = new StringBuilder();
            foreach (var val in value)
            {
                sb.Append(val.x).Append(delimiterVector).Append(val.y).Append(delimiterVector).Append(val.z).Append(delimiter);
            }
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }
        public static string Vector3IntArrayToString(object data, char delimiter = ';', char delimiterVector = ',')
        {
            //Vector3 value = (Vector3)Convert.ChangeType(data,typeof(Vector3));
            Vector3Int[] value = (Vector3Int[])data;
            StringBuilder sb = new StringBuilder();
            foreach (var val in value)
            {
                sb.Append(val.x).Append(delimiterVector).Append(val.y).Append(delimiterVector).Append(val.z).Append(delimiter);
            }
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }
        public static string Vector4ArrayToString(object data, char delimiter = ';', char delimiterVector = ',')
        {
            //Vector3 value = (Vector3)Convert.ChangeType(data,typeof(Vector3));
            Vector4[] value = (Vector4[])data;
            StringBuilder sb = new StringBuilder();
            foreach (var val in value)
            {
                sb.Append(val.x).Append(delimiterVector).Append(val.y).Append(delimiterVector).Append(val.z).Append(delimiterVector).Append(val.w).Append(delimiter);
            }
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }

        public static string ConvertToString(object data, Type t, DelimitersAttribute delimiterAttributes)
        {
            object value = null;
            if (t == typeof(float) || t == typeof(double) || t == typeof(short) || t == typeof(int) || t == typeof(long))
            {
                value = Convert.ToString(data);
            }
            else if (t == typeof(string) || t.IsArray)
            {
                value = data;
            }
            else if (t == typeof(bool))
                value = Convert.ToString(data);

            if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                //var nc = new NullableConverter(t);
                return string.Empty;
            }

            if (t.IsEnum)
            {
                // for enum type, first get value by string then convert it to enum.
                value = data;
                return value.ToString();
            }
            else if (t == typeof(Vector2) || t == typeof(Vector2Int) || t == typeof(Vector3) || t == typeof(Vector3Int) || t == typeof(Vector4))
            {
                char delimiter = ',';
                if (delimiterAttributes != null)
                {
                    string delimiters = delimiterAttributes.Delimiters;
                    try
                    {
                        delimiter = delimiters[0];
                    }
                    catch { }
                }
                if (t == typeof(Vector2))
                    return ConvertExt.Vector2ToString(data, delimiter);
                if (t == typeof(Vector2Int))
                    return ConvertExt.Vector2IntToString(data, delimiter);
                if (t == typeof(Vector3))
                    return ConvertExt.Vector3ToString(data, delimiter);
                if (t == typeof(Vector3Int))
                    return ConvertExt.Vector3IntToString(data, delimiter);
                if (t == typeof(Vector4))
                    return ConvertExt.Vector4ToString(data, delimiter);
            }
            else if (t.IsArray)
            {
                char delimiter = ',';
                char delimiter1 = ';';
                if (delimiterAttributes != null)
                {
                    string delimiters = delimiterAttributes.Delimiters;
                    try
                    {
                        delimiter = delimiters[0];
                        delimiter1 = delimiters[1];
                    }
                    catch { }
                }
                if (t.GetElementType() == typeof(float))
                    return ConvertExt.SingleArrayToString(data, delimiter);
                if (t.GetElementType() == typeof(double))
                    return ConvertExt.DoubleArrayToString(data, delimiter);
                if (t.GetElementType() == typeof(short))
                    return ConvertExt.Int16ArrayToString(data, delimiter);
                if (t.GetElementType() == typeof(int))
                    return ConvertExt.Int32ArrayToString(data, delimiter);
                if (t.GetElementType() == typeof(long))
                    return ConvertExt.Int64ArrayToString(data, delimiter);
                if (t.GetElementType() == typeof(string))
                    return ConvertExt.StringArrayToString(data, delimiter);
                if (t.GetElementType() == typeof(Vector2))
                    return ConvertExt.Vector2ArrayToString(data, delimiter1, delimiter);
                if (t.GetElementType() == typeof(Vector2Int))
                    return ConvertExt.Vector2IntArrayToString(data, delimiter1, delimiter);
                if (t.GetElementType() == typeof(Vector3))
                    return ConvertExt.Vector3ArrayToString(data, delimiter1, delimiter);
                if (t.GetElementType() == typeof(Vector3Int))
                    return ConvertExt.Vector3IntArrayToString(data, delimiter1, delimiter);
                if (t.GetElementType() == typeof(Vector4))
                    return ConvertExt.Vector4ArrayToString(data, delimiter1, delimiter);
            }

            // for all other types, convert its corresponding type.
            return value.ToString();
        }
    }
}